#include "stm32f10x.h"                  // Device header
#include "ultrasonic.h"
#include "Delay.h"
//#include "OLED.h"

#define TIMARR	10000
//#define Ultrasonicsta	(500 / (5000 / 1000))

// 全局变量
UltrasonicState uState = US_IDLE;// 状态机枚举
volatile uint16_t system_time_ms = 0;  // TIM3溢出计数器
volatile uint32_t pulse_start_time = 0;  // 脉冲开始时间
volatile uint8_t dataReady = 0;// 新数据就绪标志
volatile float finalDistance = 0;// 距离

//volatile uint16_t error = 0;

/**
  * @brief  初始化超声波模块
  */
void Ultrasonic_Init(void) 
{
    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	
	// 配置TRIG引脚(输出)
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOA, GPIO_Pin_3);  // 初始低电平
    
    // 配置PA2为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置PA2为EXTI2中断源
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
    
    // EXTI配置
	EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line2;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  // 双边沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    // 配置EXTI2中断
	NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 初始化状态
    uState = US_IDLE;
    dataReady = 0;
    system_time_ms = 0;
}

/**
  * @brief  超声波状态机处理
  */
void Ultrasonic_Process(void) 
{   
    // 状态机处理
    switch (uState) 
    {
        case US_IDLE:
            // 空闲状态，不做处理
            break;
            
        case US_TRIG_START:
            // 拉高TRIG并记录开始时间
            GPIO_SetBits(GPIOA, GPIO_Pin_3);
            Delay_us(20);
			GPIO_ResetBits(GPIOA, GPIO_Pin_3);
            uState = US_WAIT_ECHO_END;
            break;
            
        case US_WAIT_ECHO_END:
			// 收到距离
            if (dataReady == 1) 
            {
                // 超时未收到回波
                uState = US_IDLE;
				break;
            }
			
			// 超时处理(60ms)
            if (system_time_ms > 60) 
            {
                // 超时未收到回波
                uState = US_IDLE;
            }
            break;
			
		default:
			break;
    }
}

/**
  * @brief  启动超声波测量
  */
void Ultrasonic_StartMeasurement(void) 
{
	system_time_ms++;  // 维护溢出计数器
	
	if(system_time_ms > 50) 
	{
		system_time_ms = 0;

		if (uState == US_IDLE) 
		{
			uState = US_TRIG_START;
			dataReady = 0;
		}
	}
}

/**
  * @brief  获取测量结果
  * @retval 距离(cm)，未就绪时返回-1
  */
float Ultrasonic_GetDistance(void) 
{
    if (dataReady)
    {
		dataReady = 0;
        return finalDistance;
    }
    return -1.0f;
}

// EXTI2中断服务函数
void EXTI2_IRQHandler(void) 
{
    if (EXTI_GetITStatus(EXTI_Line2) != RESET) 
	{
		EXTI_ClearITPendingBit(EXTI_Line2);  // 清除中断标志
		
        uint32_t current_time, current_count;
        
        // 获取当前时间和计数器值
        current_time = system_time_ms;
        current_count = TIM_GetCounter(TIM3);
        
        // 检测引脚状态
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == Bit_SET) 
		{
            // 上升沿 - 记录起始时间
            pulse_start_time = current_time * TIMARR + current_count;  // 转换为微秒
        } 
		
		else 
		{
            // 下降沿 - 计算持续时间
            uint32_t end_time = current_time * TIMARR + current_count;
			uint32_t pulse_duration = end_time - pulse_start_time;
			// 计算距离(cm) 声速340m/s = 0.034cm/us, 来回距离所以除以2
			__DSB();		// 插入内存屏障
			finalDistance = pulse_duration * 0.017f;
			dataReady = 1;  // 设置数据就绪标志
        }
        

    }
}
